// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package sync

import (
	"internal/race"
	"sync/atomic"
	"unsafe"
)

// 运行时/rwmutex中有一个此文件的修改副本。去
// 如果您在此处进行任何更改，请查看是否应该在此处进行更改。

// RWMutex是读写互斥锁。
// 锁可以由任意数量的读卡器或单个写卡器持有。
// RWMutex的零值是一个未锁定的mutex。
// 
// 首次使用后不得复制RWMutex。
// 
// 如果一个goroutine拥有一个用于读取的RWMutex，而另一个goroutine可能会
// 调用锁，则在释放初始读取锁之前，任何goroutine都不应期望能够获取读取锁
// 。特别是，这禁止
// 递归读取锁定。这是为了确保锁最终变成
// 可用；被阻止的锁调用会阻止新读卡器获取
// 锁。
type RWMutex struct {
	w           Mutex  // 如果有待处理的写入程序
	writerSem   uint32 // 写入程序等待完成的信号
	readerSem   uint32 // 读取程序等待完成的信号
	readerCount int32  // 待处理的读取程序
	readerWait  int32  // 离开的读取程序
}

const rwmutexMaxReaders = 1 << 30

// 在通过：
// Unlock->Lock:readerSem 
// Unlock->RLock:readerSem 
// RUnlock->Lock:writerSem 
// 
// 以下方法暂时禁用对比赛同步
// 事件的处理，以便为比赛
// 检测器提供更精确的上述模型。例如，原子。RLock中的AddInt32似乎不应该提供
// 获取发布语义，这将错误地同步正在比赛的
// 读卡器，因此可能会丢失比赛。

// RLock锁定rw进行读取。
// 
// 不应用于递归读取锁定；被阻止的锁
// 调用将阻止新读卡器获取锁。请参阅关于RWMutex类型的
// 文档。
func (rw *RWMutex) RLock() {
	if race.Enabled {
		_ = rw.w.state
		race.Disable()
	}
	if atomic.AddInt32(&rw.readerCount, 1) < 0 {
		// 一位作者正在等待，请等待。
		runtime_SemacquireMutex(&rw.readerSem, false, 0)
	}
	if race.Enabled {
		race.Enable()
		race.Acquire(unsafe.Pointer(&rw.readerSem))
	}
}

// TryRLock尝试锁定rw进行读取，并报告是否成功。
// 
// 请注意，虽然TryRLock的正确用法确实存在，但它们很少见，而TryRLock的使用往往是一个更深层次的问题的标志
// 在特定的互斥体使用中。
func (rw *RWMutex) TryRLock() bool {
	if race.Enabled {
		_ = rw.w.state
		race.Disable()
	}
	for {
		c := atomic.LoadInt32(&rw.readerCount)
		if c < 0 {
			if race.Enabled {
				race.Enable()
			}
			return false
		}
		if atomic.CompareAndSwapInt32(&rw.readerCount, c, c+1) {
			if race.Enabled {
				race.Enable()
				race.Acquire(unsafe.Pointer(&rw.readerSem))
			}
			return true
		}
	}
}

// RUnlock撤销一个RLock调用；
// 它不会影响其他同步读卡器。
// 如果rw在进入RUnlock时没有被锁定以读取
// 则为运行时错误。
func (rw *RWMutex) RUnlock() {
	if race.Enabled {
		_ = rw.w.state
		race.ReleaseMerge(unsafe.Pointer(&rw.writerSem))
		race.Disable()
	}
	if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
		// 概述了允许内联快速路径的慢路径
		rw.rUnlockSlow(r)
	}
	if race.Enabled {
		race.Enable()
	}
}

func (rw *RWMutex) rUnlockSlow(r int32) {
	if r+1 == 0 || r+1 == -rwmutexMaxReaders {
		race.Enable()
		throw("sync: RUnlock of unlocked RWMutex")
	}
	// 写入程序正在等待。
	if atomic.AddInt32(&rw.readerWait, -1) == 0 {
		// 最后一个读卡器将解锁写入器。
		runtime_Semrelease(&rw.writerSem, false, 1)
	}
}

// 为写入锁定rw。
// 如果锁已被锁定用于读取或写入，
// 将锁定，直到锁可用。首先，解决与其他作家的竞争。
func (rw *RWMutex) Lock() {
	if race.Enabled {
		_ = rw.w.state
		race.Disable()
	}
	rw.w.Lock()
	// 向读者宣布，有一位作家即将上任。
	r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
	// 等待活动的读卡器。
	if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
		runtime_SemacquireMutex(&rw.writerSem, false, 0)
	}
	if race.Enabled {
		race.Enable()
		race.Acquire(unsafe.Pointer(&rw.readerSem))
		race.Acquire(unsafe.Pointer(&rw.writerSem))
	}
}

// TryLock试图锁定rw进行写作，并报告是否成功。注意，虽然TryLock的正确用法确实存在，但它们很少见，而且TryLock的使用往往是一个更深层次问题的标志。
func (rw *RWMutex) TryLock() bool {
	if race.Enabled {
		_ = rw.w.state
		race.Disable()
	}
	if !rw.w.TryLock() {
		if race.Enabled {
			race.Enable()
		}
		return false
	}
	if !atomic.CompareAndSwapInt32(&rw.readerCount, 0, -rwmutexMaxReaders) {
		rw.w.Unlock()
		if race.Enabled {
			race.Enable()
		}
		return false
	}
	if race.Enabled {
		race.Enable()
		race.Acquire(unsafe.Pointer(&rw.readerSem))
		race.Acquire(unsafe.Pointer(&rw.writerSem))
	}
	return true
}

// Unlock解锁rw以供写入。如果rw为
// 未锁定写入解锁条目，则为运行时错误。
// 
// 与互斥体一样，锁定的RW互斥体与特定的
// goroutine不关联。一个goroutine可能会锁定一个RWMutex，然后
// 安排另一个goroutine运行锁定（解锁）它。
func (rw *RWMutex) Unlock() {
	if race.Enabled {
		_ = rw.w.state
		race.Release(unsafe.Pointer(&rw.readerSem))
		race.Disable()
	}

	// 向读者宣布，没有活跃的作家。
	r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
	if r >= rwmutexMaxReaders {
		race.Enable()
		throw("sync: Unlock of unlocked RWMutex")
	}
	// 取消阻止被阻止的读卡器（如果有）。
	for i := 0; i < int(r); i++ {
		runtime_Semrelease(&rw.readerSem, false, 0)
	}
	// 允许其他作者继续。
	rw.w.Unlock()
	if race.Enabled {
		race.Enable()
	}
}

// RLocker返回一个Locker接口，该接口通过调用rw来实现锁定和解锁方法。洛克和罗克。朗洛克。
func (rw *RWMutex) RLocker() Locker {
	return (*rlocker)(rw)
}

type rlocker RWMutex

func (r *rlocker) Lock()   { (*RWMutex)(r).RLock() }
func (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() }
